<?php

namespace App\Kits\Resources;

use App\Kits\ResponseCode;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class ApiResource extends JsonResource
{
    protected $exception;
    protected $message;
    protected $code;

    public function __construct($resource, string $message = null, int $code = ResponseCode::CODE_200)
    {


        if ($resource instanceof NotFoundHttpException) {
            $this->exception = $resource;
            $this->code = ResponseCode::CODE_404;
            $this->message = 'NotFound';
            $resource = null;
        } elseif ($resource instanceof \Throwable) {
            $this->exception = $resource;
            if ($code === ResponseCode::CODE_200) {
                $code = ResponseCode::CODE_205;
            }
            $this->code = $resource->getCode() ?: $code;
            $this->message = $message ?? $resource->getMessage();
            $resource = null;
        } else {
            $this->code = $code;
            $this->message = $message;
        }


        parent::__construct($resource);
    }

    public function with($request)
    {
        $data = $this->withDefault();
        if ($this->exception) {
            return $this->withErrorMessage($data);
        }
        return $data;

    }

    protected function withErrorMessage(array $data = [])
    {
        $resource = $this->exception;
        if (config('app.debug')) {
            $data['file'] = $resource->getFile();
            $data['line'] = $resource->getLine();
            $data['trace'] = $resource->getTrace();
        }
        return $data;
    }

    /**
     * data字段非数组处理
     * @param null $request
     * @return array|null
     */
    public function resolve($request = null)
    {
        $resource = $this->resource;
        if (is_null($resource) || (!is_array($resource) && !is_object($resource))) {
            return $resource;
        }
        return parent::resolve($request);
    }


    protected function withDefault()
    {
        return [
            'code' => $this->code ?? ResponseCode::CODE_200,
            'message' => $this->message ?? '',
        ];
    }

    /**
     * @param Request $request
     * @return JsonResponse|mixed
     */
    public function toResponse($request)
    {

        return (new ApiResourceResponse($this))->toResponse($request);
    }

}
